﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Diagnostics;
using TPOJ.Core.Utils;

namespace TPOJ.CoreWF
{

    public sealed class CompileActivity : CodeActivity<Result>
    {
        private const int WAIT_MILLISECONDS = 60000;
        private Result result = new Result();
        private string fileName, args;

        public InArgument<string> InputPath { get; set; }
        public InArgument<string> OutputPath { get; set; }
        public InArgument<Language> Language { get; set; }

        protected override Result Execute(CodeActivityContext context)
        {
            ParseCommandLineArgs(context);
            return Compile();
        }

        /// <summary>
        /// Parse the language compile command line to initialise compile process file name and arguements.
        /// </summary>
        private void ParseCommandLineArgs(CodeActivityContext context)
        {
            string cmd = context.GetValue(Language).CompileCommandLine.Replace("%1", context.GetValue(InputPath))
                                            .Replace("%2", context.GetValue(OutputPath));
            int index = cmd.IndexOf(' ');
            this.fileName = cmd.Substring(0, index);
            this.args = cmd.Substring(index, cmd.Length - index);
        }

        /// <summary>
        /// Run the compiler.
        /// </summary>
        /// <returns>The compiling result</returns>
        public Result Compile()
        {
            result.ResultType = TPOJ.CoreWF.ResultType.CompileError;

            ProcessStartInfo startInfo = new ProcessStartInfo(this.fileName);
            startInfo.Arguments = this.args;
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            startInfo.CreateNoWindow = true;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;

            Process p = Process.Start(startInfo);
            if (p.WaitForExit(WAIT_MILLISECONDS))
            {
                result.ExitCode = p.ExitCode;
                result.ErrorMessage = p.StandardOutput.ReadToEnd().FormatCompileWarning();
            }
            else
            {
                p.Kill();
                result.ExitCode = int.MinValue;
                result.ErrorMessage = "Compile System Failure.";
            }
            return result;
        }
    }
}
